<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="utf-8" />
    <title>geosnap.analyze.analytics &#8212; geosnap v0.3.1 Manual</title>
    <link rel="stylesheet" href="../../../_static/bootstrap-sphinx.css" type="text/css" />
    <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
    <link rel="stylesheet" type="text/css" href="../../../_static/pysal-styles.css" />
    <script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
    <script src="../../../_static/jquery.js"></script>
    <script src="../../../_static/underscore.js"></script>
    <script src="../../../_static/doctools.js"></script>
    <script src="../../../_static/language_data.js"></script>
    <link rel="shortcut icon" href="../../../_static/geosnap.ico"/>
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.html" />
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
<meta name="apple-mobile-web-app-capable" content="yes">
<script type="text/javascript" src="../../../_static/js/jquery-1.11.0.min.js "></script>
<script type="text/javascript" src="../../../_static/js/jquery-fix.js "></script>
<script type="text/javascript" src="../../../_static/bootstrap-3.3.7/js/bootstrap.min.js "></script>
<script type="text/javascript" src="../../../_static/bootstrap-sphinx.js "></script>

  </head><body>

  <div id="navbar" class="navbar navbar-default navbar-fixed-top">
    <div class="container">
      <div class="navbar-header">
        <!-- .btn-navbar is used as the toggle for collapsed navbar content -->
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="../../../index.html"><span><img src="../../../_static/geosnap.svg"></span>
          geosnap</a>
        <span class="navbar-text navbar-version pull-left"><b>0.3.1</b></span>
      </div>

        <div class="collapse navbar-collapse nav-collapse">
          <ul class="nav navbar-nav">
            
                <li><a href="../../../installation.html">Installation</a></li>
                <li><a href="../../../api.html">API</a></li>
                <li><a href="../../../data.html">Data</a></li>
                <li><a href="https://spatialucr.github.io/geosnap-guide/">User Guide</a></li>
                <li><a href="../../../references.html">References</a></li>
            
            
              <li class="dropdown globaltoc-container">
  <a role="button"
     id="dLabelGlobalToc"
     data-toggle="dropdown"
     data-target="#"
     href="../../../index.html">Site <b class="caret"></b></a>
  <ul class="dropdown-menu globaltoc"
      role="menu"
      aria-labelledby="dLabelGlobalToc"><p class="caption"><span class="caption-text">Contents:</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../../installation.html">Installation</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../../../installation.html#installing-a-released-version">Installing a released version</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../../installation.html#installing-development-version">Installing development version</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../../api.html">API</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../../../api.html#io-module">IO Module</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../../api.html#the-community-class">The Community Class</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../../api.html#analyze-module">Analyze Module</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../../api.html#harmonize-module">Harmonize Module</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../../api.html#visualize-module">Visualize Module</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../../references.html">References</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../data.html">Data</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../../../data.html#tabular-data">Tabular Data</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../../data.html#geo-data">Geo Data</a></li>
</ul>
</li>
</ul>
</ul>
</li>
              
                <li class="dropdown">
  <a role="button"
     id="dLabelLocalToc"
     data-toggle="dropdown"
     data-target="#"
     href="#">Page <b class="caret"></b></a>
  <ul class="dropdown-menu localtoc"
      role="menu"
      aria-labelledby="dLabelLocalToc"></ul>
</li>
              
            
            
            
            
            
          </ul>

          
            
<form class="navbar-form navbar-right" action="../../../search.html" method="get">
 <div class="form-group">
  <input type="text" name="q" class="form-control" placeholder="Search" />
 </div>
  <input type="hidden" name="check_keywords" value="yes" />
  <input type="hidden" name="area" value="default" />
</form>
          
        </div>
    </div>
  </div>

<div class="container">
  <div class="row">
    <div class="body col-md-12 content" role="main">
      
  <h1>Source code for geosnap.analyze.analytics</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;Tools for the spatial analysis of neighborhood change.&quot;&quot;&quot;</span>

<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>

<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="nn">pd</span>
<span class="kn">from</span> <span class="nn">sklearn.preprocessing</span> <span class="kn">import</span> <span class="n">StandardScaler</span>

<span class="kn">from</span> <span class="nn">libpysal.weights</span> <span class="kn">import</span> <span class="n">attach_islands</span>
<span class="kn">from</span> <span class="nn">libpysal.weights.contiguity</span> <span class="kn">import</span> <span class="n">Queen</span><span class="p">,</span> <span class="n">Rook</span>
<span class="kn">from</span> <span class="nn">libpysal.weights.distance</span> <span class="kn">import</span> <span class="n">KNN</span>

<span class="kn">from</span> <span class="nn">.._data</span> <span class="kn">import</span> <span class="n">_Map</span>
<span class="kn">from</span> <span class="nn">.cluster</span> <span class="kn">import</span> <span class="p">(</span>
    <span class="n">affinity_propagation</span><span class="p">,</span>
    <span class="n">azp</span><span class="p">,</span>
    <span class="n">gaussian_mixture</span><span class="p">,</span>
    <span class="n">hdbscan</span><span class="p">,</span>
    <span class="n">kmeans</span><span class="p">,</span>
    <span class="n">max_p</span><span class="p">,</span>
    <span class="n">skater</span><span class="p">,</span>
    <span class="n">spectral</span><span class="p">,</span>
    <span class="n">spenc</span><span class="p">,</span>
    <span class="n">ward</span><span class="p">,</span>
    <span class="n">ward_spatial</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">ModelResults</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span>
    <span class="s2">&quot;model&quot;</span><span class="p">,</span> <span class="p">[</span><span class="s2">&quot;X&quot;</span><span class="p">,</span> <span class="s2">&quot;columns&quot;</span><span class="p">,</span> <span class="s2">&quot;labels&quot;</span><span class="p">,</span> <span class="s2">&quot;instance&quot;</span><span class="p">,</span> <span class="s2">&quot;W&quot;</span><span class="p">],</span> <span class="n">rename</span><span class="o">=</span><span class="kc">False</span>
<span class="p">)</span>


<div class="viewcode-block" id="cluster"><a class="viewcode-back" href="../../../generated/geosnap.analyze.cluster.html#geosnap.analyze.cluster">[docs]</a><span class="k">def</span> <span class="nf">cluster</span><span class="p">(</span>
    <span class="n">gdf</span><span class="p">,</span>
    <span class="n">n_clusters</span><span class="o">=</span><span class="mi">6</span><span class="p">,</span>
    <span class="n">method</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
    <span class="n">best_model</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
    <span class="n">columns</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
    <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
    <span class="n">time_var</span><span class="o">=</span><span class="s2">&quot;year&quot;</span><span class="p">,</span>
    <span class="n">id_var</span><span class="o">=</span><span class="s2">&quot;geoid&quot;</span><span class="p">,</span>
    <span class="n">scaler</span><span class="o">=</span><span class="s1">&#39;std&#39;</span><span class="p">,</span>
    <span class="n">pooling</span><span class="o">=</span><span class="s2">&quot;fixed&quot;</span><span class="p">,</span>
    <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
<span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Create a geodemographic typology by running a cluster analysis on the study area&#39;s neighborhood attributes.</span>

<span class="sd">    Parameters</span>
<span class="sd">    ----------</span>
<span class="sd">    gdf : geopandas.GeoDataFrame, required</span>
<span class="sd">        long-form GeoDataFrame containing neighborhood attributes</span>
<span class="sd">    n_clusters : int, required</span>
<span class="sd">        the number of clusters to model. The default is 6).</span>
<span class="sd">    method : str in [&#39;kmeans&#39;, &#39;ward&#39;, &#39;affinity_propagation&#39;, &#39;spectral&#39;,&#39;gaussian_mixture&#39;, &#39;hdbscan&#39;], required</span>
<span class="sd">        the clustering algorithm used to identify neighborhood types</span>
<span class="sd">    best_model : bool, optional</span>
<span class="sd">        if using a gaussian mixture model, use BIC to choose the best</span>
<span class="sd">        n_clusters. (the default is False).</span>
<span class="sd">    columns : list-like, required</span>
<span class="sd">        subset of columns on which to apply the clustering</span>
<span class="sd">    verbose : bool, optional</span>
<span class="sd">        whether to print warning messages (the default is False).</span>
<span class="sd">    time_var : str, optional</span>
<span class="sd">        which column on the dataframe defines time and or sequencing of the</span>
<span class="sd">        long-form data. Default is &quot;year&quot;</span>
<span class="sd">    id_var : str, optional</span>
<span class="sd">        which column on the long-form dataframe identifies the stable units</span>
<span class="sd">        over time. In a wide-form dataset, this would be the unique index</span>
<span class="sd">    scaler : None or scaler from sklearn.preprocessing, optional</span>
<span class="sd">        a scikit-learn preprocessing class that will be used to rescale the</span>
<span class="sd">        data. Defaults to sklearn.preprocessing.StandardScaler</span>
<span class="sd">    pooling : [&quot;fixed&quot;, &quot;pooled&quot;, &quot;unique&quot;], optional (default=&#39;fixed&#39;)</span>
<span class="sd">        How to treat temporal data when applying scaling. Options include:</span>

<span class="sd">        * fixed : scaling is fixed to each time period</span>
<span class="sd">        * pooled : data are pooled across all time periods</span>
<span class="sd">        * unique : if scaling, apply the scaler to each time period, then generate</span>
<span class="sd">          clusters unique to each time period.</span>

<span class="sd">    Returns</span>
<span class="sd">    -------</span>
<span class="sd">    gdf : geopandas.GeoDataFrame</span>
<span class="sd">        GeoDataFrame with a column of neighborhood cluster labels</span>
<span class="sd">        appended as a new column. If cluster method exists as a column on the DataFrame</span>
<span class="sd">        then the column will be incremented.</span>

<span class="sd">    model : named tuple</span>
<span class="sd">        A tuple with attributes X, columns, labels, instance, W, which store the</span>
<span class="sd">        input matrix, column labels, fitted model instance, and spatial weights matrix</span>

<span class="sd">    model_name : str</span>
<span class="sd">        name of model to be stored in a Community</span>

<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">specification</span> <span class="o">=</span> <span class="p">{</span>
        <span class="s2">&quot;ward&quot;</span><span class="p">:</span> <span class="n">ward</span><span class="p">,</span>
        <span class="s2">&quot;kmeans&quot;</span><span class="p">:</span> <span class="n">kmeans</span><span class="p">,</span>
        <span class="s2">&quot;affinity_propagation&quot;</span><span class="p">:</span> <span class="n">affinity_propagation</span><span class="p">,</span>
        <span class="s2">&quot;gaussian_mixture&quot;</span><span class="p">:</span> <span class="n">gaussian_mixture</span><span class="p">,</span>
        <span class="s2">&quot;spectral&quot;</span><span class="p">:</span> <span class="n">spectral</span><span class="p">,</span>
        <span class="s2">&quot;hdbscan&quot;</span><span class="p">:</span> <span class="n">hdbscan</span><span class="p">,</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="n">scaler</span> <span class="o">==</span> <span class="s2">&quot;std&quot;</span><span class="p">:</span>
        <span class="n">scaler</span> <span class="o">=</span> <span class="n">StandardScaler</span><span class="p">()</span>
    <span class="k">if</span> <span class="n">method</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">specification</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
            <span class="s2">&quot;`method` must of one of [&#39;kmeans&#39;, &#39;ward&#39;, &#39;affinity_propagation&#39;, &#39;spectral&#39;, &#39;gaussian_mixture&#39;, &#39;hdbscan&#39;]&quot;</span>
        <span class="p">)</span>

    <span class="c1"># if we already have a column named after the clustering method, then increment it.</span>
    <span class="k">if</span> <span class="n">method</span> <span class="ow">in</span> <span class="n">gdf</span><span class="o">.</span><span class="n">columns</span><span class="o">.</span><span class="n">tolist</span><span class="p">():</span>
        <span class="n">model_name</span> <span class="o">=</span> <span class="n">method</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">gdf</span><span class="o">.</span><span class="n">columns</span><span class="p">[</span><span class="n">gdf</span><span class="o">.</span><span class="n">columns</span><span class="o">.</span><span class="n">str</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">method</span><span class="p">)]))</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">model_name</span> <span class="o">=</span> <span class="n">method</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">columns</span><span class="p">:</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;You must provide a subset of columns as input&quot;</span><span class="p">)</span>

    <span class="n">times</span> <span class="o">=</span> <span class="n">gdf</span><span class="p">[</span><span class="n">time_var</span><span class="p">]</span><span class="o">.</span><span class="n">unique</span><span class="p">()</span>
    <span class="n">gdf</span> <span class="o">=</span> <span class="n">gdf</span><span class="o">.</span><span class="n">set_index</span><span class="p">([</span><span class="n">time_var</span><span class="p">,</span> <span class="n">id_var</span><span class="p">])</span>

    <span class="c1"># this is the dataset we&#39;ll operate on</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">gdf</span><span class="o">.</span><span class="n">copy</span><span class="p">()[</span><span class="n">columns</span><span class="p">]</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">dropna</span><span class="p">(</span><span class="n">how</span><span class="o">=</span><span class="s2">&quot;any&quot;</span><span class="p">,</span> <span class="n">subset</span><span class="o">=</span><span class="n">columns</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">scaler</span><span class="p">:</span>

        <span class="k">if</span> <span class="n">pooling</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">&quot;fixed&quot;</span><span class="p">,</span> <span class="s2">&quot;unique&quot;</span><span class="p">]:</span>
            <span class="c1"># if fixed (or unique), scale within each time period</span>
            <span class="k">for</span> <span class="n">time</span> <span class="ow">in</span> <span class="n">times</span><span class="p">:</span>
                <span class="n">data</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">time</span><span class="p">]</span> <span class="o">=</span> <span class="n">scaler</span><span class="o">.</span><span class="n">fit_transform</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">time</span><span class="p">]</span><span class="o">.</span><span class="n">values</span><span class="p">)</span>

        <span class="k">elif</span> <span class="n">pooling</span> <span class="o">==</span> <span class="s2">&quot;pooled&quot;</span><span class="p">:</span>
            <span class="c1"># if pooled, scale the whole series at once</span>
            <span class="n">data</span><span class="o">.</span><span class="n">loc</span><span class="p">[:,</span> <span class="n">columns</span><span class="p">]</span> <span class="o">=</span> <span class="n">scaler</span><span class="o">.</span><span class="n">fit_transform</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">values</span><span class="p">)</span>

    <span class="c1"># the rescalar can create nans if a column has no variance, so fill with 0</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">fillna</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">pooling</span> <span class="o">!=</span> <span class="s2">&quot;unique&quot;</span><span class="p">:</span>

        <span class="c1"># run the cluster model then join the labels back to the original data</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">specification</span><span class="p">[</span><span class="n">method</span><span class="p">](</span>
            <span class="n">data</span><span class="p">,</span>
            <span class="n">n_clusters</span><span class="o">=</span><span class="n">n_clusters</span><span class="p">,</span>
            <span class="n">best_model</span><span class="o">=</span><span class="n">best_model</span><span class="p">,</span>
            <span class="n">verbose</span><span class="o">=</span><span class="n">verbose</span><span class="p">,</span>
            <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
        <span class="p">)</span>
        <span class="n">labels</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">labels_</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">reset_index</span><span class="p">()</span>
        <span class="n">clusters</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span>
            <span class="p">{</span><span class="n">model_name</span><span class="p">:</span> <span class="n">labels</span><span class="p">,</span> <span class="n">time_var</span><span class="p">:</span> <span class="n">data</span><span class="p">[</span><span class="n">time_var</span><span class="p">],</span> <span class="n">id_var</span><span class="p">:</span> <span class="n">data</span><span class="p">[</span><span class="n">id_var</span><span class="p">]}</span>
        <span class="p">)</span>
        <span class="n">clusters</span><span class="o">.</span><span class="n">set_index</span><span class="p">([</span><span class="n">time_var</span><span class="p">,</span> <span class="n">id_var</span><span class="p">],</span> <span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
        <span class="n">clusters</span> <span class="o">=</span> <span class="n">clusters</span><span class="p">[</span><span class="o">~</span><span class="n">clusters</span><span class="o">.</span><span class="n">index</span><span class="o">.</span><span class="n">duplicated</span><span class="p">(</span><span class="n">keep</span><span class="o">=</span><span class="s1">&#39;first&#39;</span><span class="p">)]</span>
        <span class="n">gdf</span> <span class="o">=</span> <span class="n">gdf</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">clusters</span><span class="p">,</span> <span class="n">how</span><span class="o">=</span><span class="s2">&quot;left&quot;</span><span class="p">)</span>
        <span class="n">gdf</span> <span class="o">=</span> <span class="n">gdf</span><span class="o">.</span><span class="n">reset_index</span><span class="p">()</span>
        <span class="n">results</span> <span class="o">=</span> <span class="n">ModelResults</span><span class="p">(</span>
            <span class="n">X</span><span class="o">=</span><span class="n">data</span><span class="o">.</span><span class="n">values</span><span class="p">,</span> <span class="n">columns</span><span class="o">=</span><span class="n">columns</span><span class="p">,</span> <span class="n">labels</span><span class="o">=</span><span class="n">model</span><span class="o">.</span><span class="n">labels_</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="n">model</span><span class="p">,</span> <span class="n">W</span><span class="o">=</span><span class="kc">None</span>
        <span class="p">)</span>
        <span class="k">return</span> <span class="n">gdf</span><span class="p">,</span> <span class="n">results</span><span class="p">,</span> <span class="n">model_name</span>

    <span class="k">elif</span> <span class="n">pooling</span> <span class="o">==</span> <span class="s1">&#39;unique&#39;</span><span class="p">:</span>
        <span class="n">models</span> <span class="o">=</span> <span class="n">_Map</span><span class="p">()</span>
        <span class="n">gdf</span><span class="p">[</span><span class="n">model_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">nan</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">reset_index</span><span class="p">()</span>

        <span class="k">for</span> <span class="n">time</span> <span class="ow">in</span> <span class="n">times</span><span class="p">:</span>

            <span class="n">df</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">data</span><span class="p">[</span><span class="n">time_var</span><span class="p">]</span> <span class="o">==</span> <span class="n">time</span><span class="p">]</span>

            <span class="n">model</span> <span class="o">=</span> <span class="n">specification</span><span class="p">[</span><span class="n">method</span><span class="p">](</span>
                <span class="n">df</span><span class="p">[</span><span class="n">columns</span><span class="p">],</span>
                <span class="n">n_clusters</span><span class="o">=</span><span class="n">n_clusters</span><span class="p">,</span>
                <span class="n">best_model</span><span class="o">=</span><span class="n">best_model</span><span class="p">,</span>
                <span class="n">verbose</span><span class="o">=</span><span class="n">verbose</span><span class="p">,</span>
                <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
            <span class="p">)</span>

            <span class="n">labels</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">labels_</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span>
            <span class="n">clusters</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span>
                <span class="p">{</span><span class="n">model_name</span><span class="p">:</span> <span class="n">labels</span><span class="p">,</span> <span class="n">time_var</span><span class="p">:</span> <span class="n">time</span><span class="p">,</span> <span class="n">id_var</span><span class="p">:</span> <span class="n">df</span><span class="p">[</span><span class="n">id_var</span><span class="p">]}</span>
            <span class="p">)</span>
            <span class="n">clusters</span><span class="o">.</span><span class="n">set_index</span><span class="p">([</span><span class="n">time_var</span><span class="p">,</span> <span class="n">id_var</span><span class="p">],</span> <span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
            <span class="n">gdf</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">clusters</span><span class="p">)</span>
            <span class="n">results</span> <span class="o">=</span> <span class="n">ModelResults</span><span class="p">(</span>
                <span class="n">X</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="n">columns</span><span class="p">]</span><span class="o">.</span><span class="n">values</span><span class="p">,</span>
                <span class="n">columns</span><span class="o">=</span><span class="n">columns</span><span class="p">,</span>
                <span class="n">labels</span><span class="o">=</span><span class="n">model</span><span class="o">.</span><span class="n">labels_</span><span class="p">,</span>
                <span class="n">instance</span><span class="o">=</span><span class="n">model</span><span class="p">,</span>
                <span class="n">W</span><span class="o">=</span><span class="kc">None</span>
            <span class="p">)</span>
            <span class="n">models</span><span class="p">[</span><span class="n">time</span><span class="p">]</span> <span class="o">=</span> <span class="n">results</span>

        <span class="n">gdf</span> <span class="o">=</span> <span class="n">gdf</span><span class="o">.</span><span class="n">reset_index</span><span class="p">()</span>

        <span class="k">return</span> <span class="n">gdf</span><span class="p">,</span> <span class="n">models</span><span class="p">,</span> <span class="n">model_name</span></div>


<div class="viewcode-block" id="cluster_spatial"><a class="viewcode-back" href="../../../generated/geosnap.analyze.cluster_spatial.html#geosnap.analyze.cluster_spatial">[docs]</a><span class="k">def</span> <span class="nf">cluster_spatial</span><span class="p">(</span>
    <span class="n">gdf</span><span class="p">,</span>
    <span class="n">n_clusters</span><span class="o">=</span><span class="mi">6</span><span class="p">,</span>
    <span class="n">spatial_weights</span><span class="o">=</span><span class="s2">&quot;rook&quot;</span><span class="p">,</span>
    <span class="n">method</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
    <span class="n">columns</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
    <span class="n">threshold_variable</span><span class="o">=</span><span class="s2">&quot;count&quot;</span><span class="p">,</span>
    <span class="n">threshold</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span>
    <span class="n">time_var</span><span class="o">=</span><span class="s2">&quot;year&quot;</span><span class="p">,</span>
    <span class="n">id_var</span><span class="o">=</span><span class="s2">&quot;geoid&quot;</span><span class="p">,</span>
    <span class="n">scaler</span><span class="o">=</span><span class="s2">&quot;std&quot;</span><span class="p">,</span>
    <span class="n">weights_kwargs</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
    <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
<span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Create a *spatial* geodemographic typology by running a cluster</span>
<span class="sd">    analysis on the metro area&#39;s neighborhood attributes and including a</span>
<span class="sd">    contiguity constraint.</span>

<span class="sd">    Parameters</span>
<span class="sd">    ----------</span>
<span class="sd">    gdf : geopandas.GeoDataFrame</span>
<span class="sd">        long-form geodataframe holding neighborhood attribute and geometry data.</span>
<span class="sd">    n_clusters : int</span>
<span class="sd">        the number of clusters to model. The default is 6).</span>
<span class="sd">    spatial_weights : [&#39;queen&#39;, &#39;rook&#39;] or libpysal.weights.W object</span>
<span class="sd">        spatial weights matrix specification`. By default, geosnap will calculate Rook</span>
<span class="sd">        weights, but you can also pass a libpysal.weights.W object for more control</span>
<span class="sd">        over the specification.</span>
<span class="sd">    method : str in [&#39;ward_spatial&#39;, &#39;spenc&#39;, &#39;skater&#39;, &#39;azp&#39;, &#39;max_p&#39;]</span>
<span class="sd">        the clustering algorithm used to identify neighborhood types</span>
<span class="sd">    columns : array-like</span>
<span class="sd">        subset of columns on which to apply the clustering</span>
<span class="sd">    threshold_variable : str</span>
<span class="sd">        for max-p, which variable should define `p`. The default is &quot;count&quot;,</span>
<span class="sd">        which will grow regions until the threshold number of polygons have</span>
<span class="sd">        been aggregated</span>
<span class="sd">    threshold : numeric</span>
<span class="sd">        threshold to use for max-p clustering (the default is 10).</span>
<span class="sd">    time_var : str</span>
<span class="sd">        which column on the dataframe defines time and or sequencing of the</span>
<span class="sd">        long-form data. Default is &quot;year&quot;</span>
<span class="sd">    id_var : str</span>
<span class="sd">        which column on the long-form dataframe identifies the stable units</span>
<span class="sd">        over time. In a wide-form dataset, this would be the unique index</span>
<span class="sd">    weights_kwargs : dict</span>
<span class="sd">        If passing a libpysal.weights.W instance to spatial_weights, these additional</span>
<span class="sd">        keyword arguments that will be passed to the weights constructor</span>
<span class="sd">    scaler : None or scaler class from sklearn.preprocessing</span>
<span class="sd">        a scikit-learn preprocessing class that will be used to rescale the</span>
<span class="sd">        data. Defaults to sklearn.preprocessing.StandardScaler</span>

<span class="sd">    Returns</span>
<span class="sd">    -------</span>
<span class="sd">    gdf : geopandas.GeoDataFrame</span>
<span class="sd">        GeoDataFrame with a column of neighborhood cluster labels</span>
<span class="sd">        appended as a new column. If cluster method exists as a column on the DataFrame</span>
<span class="sd">        then the column will be incremented.</span>

<span class="sd">    models : dict of named tuples</span>
<span class="sd">        tab-completable dictionary of named tuples keyed on the Community&#39;s time variable</span>
<span class="sd">        (e.g. year). The tuples store model results and have attributes X, columns, labels,</span>
<span class="sd">        instance, W, which store the input matrix, column labels, fitted model instance,</span>
<span class="sd">        and spatial weights matrix</span>

<span class="sd">    model_name : str</span>
<span class="sd">        name of model to be stored in a Community</span>

<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">specification</span> <span class="o">=</span> <span class="p">{</span>
        <span class="s2">&quot;azp&quot;</span><span class="p">:</span> <span class="n">azp</span><span class="p">,</span>
        <span class="s2">&quot;spenc&quot;</span><span class="p">:</span> <span class="n">spenc</span><span class="p">,</span>
        <span class="s2">&quot;ward_spatial&quot;</span><span class="p">:</span> <span class="n">ward_spatial</span><span class="p">,</span>
        <span class="s2">&quot;skater&quot;</span><span class="p">:</span> <span class="n">skater</span><span class="p">,</span>
        <span class="s2">&quot;max_p&quot;</span><span class="p">:</span> <span class="n">max_p</span><span class="p">,</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="n">method</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">specification</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
            <span class="s2">&quot;`method` must be one of  [&#39;ward_spatial&#39;, &#39;spenc&#39;, &#39;skater&#39;, &#39;azp&#39;, &#39;max_p&#39;]&quot;</span>
        <span class="p">)</span>

    <span class="k">if</span> <span class="n">method</span> <span class="ow">in</span> <span class="n">gdf</span><span class="o">.</span><span class="n">columns</span><span class="o">.</span><span class="n">tolist</span><span class="p">():</span>
        <span class="n">model_name</span> <span class="o">=</span> <span class="n">method</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">gdf</span><span class="o">.</span><span class="n">columns</span><span class="p">[</span><span class="n">gdf</span><span class="o">.</span><span class="n">columns</span><span class="o">.</span><span class="n">str</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">method</span><span class="p">)]))</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">model_name</span> <span class="o">=</span> <span class="n">method</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">columns</span><span class="p">:</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;You must provide a subset of columns as input&quot;</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">method</span><span class="p">:</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;You must choose a clustering algorithm to use&quot;</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">scaler</span> <span class="o">==</span> <span class="s2">&quot;std&quot;</span><span class="p">:</span>
        <span class="n">scaler</span> <span class="o">=</span> <span class="n">StandardScaler</span><span class="p">()</span>

    <span class="n">times</span> <span class="o">=</span> <span class="n">gdf</span><span class="p">[</span><span class="n">time_var</span><span class="p">]</span><span class="o">.</span><span class="n">unique</span><span class="p">()</span>
    <span class="n">gdf</span> <span class="o">=</span> <span class="n">gdf</span><span class="o">.</span><span class="n">set_index</span><span class="p">([</span><span class="n">time_var</span><span class="p">,</span> <span class="n">id_var</span><span class="p">])</span>

    <span class="c1"># this is the dataset we&#39;ll operate on</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">gdf</span><span class="o">.</span><span class="n">copy</span><span class="p">()[</span><span class="n">columns</span> <span class="o">+</span> <span class="p">[</span><span class="s2">&quot;geometry&quot;</span><span class="p">]]</span>

    <span class="n">contiguity_weights</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;queen&quot;</span><span class="p">:</span> <span class="n">Queen</span><span class="p">,</span> <span class="s2">&quot;rook&quot;</span><span class="p">:</span> <span class="n">Rook</span><span class="p">}</span>

    <span class="k">if</span> <span class="n">spatial_weights</span> <span class="ow">in</span> <span class="n">contiguity_weights</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
        <span class="n">W</span> <span class="o">=</span> <span class="n">contiguity_weights</span><span class="p">[</span><span class="n">spatial_weights</span><span class="p">]</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">W</span> <span class="o">=</span> <span class="n">spatial_weights</span>

    <span class="n">models</span> <span class="o">=</span> <span class="n">_Map</span><span class="p">()</span>
    <span class="n">ws</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="n">clusters</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">gdf</span><span class="p">[</span><span class="n">model_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">nan</span>

    <span class="c1"># loop over each time period, standardize the data and build a weights matrix</span>
    <span class="k">for</span> <span class="n">time</span> <span class="ow">in</span> <span class="n">times</span><span class="p">:</span>
        <span class="n">df</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">time</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">(</span><span class="n">how</span><span class="o">=</span><span class="s2">&quot;any&quot;</span><span class="p">,</span> <span class="n">subset</span><span class="o">=</span><span class="n">columns</span><span class="p">)</span><span class="o">.</span><span class="n">reset_index</span><span class="p">()</span>
        <span class="n">df</span><span class="p">[</span><span class="n">time_var</span><span class="p">]</span> <span class="o">=</span> <span class="n">time</span>

        <span class="k">if</span> <span class="n">scaler</span><span class="p">:</span>
            <span class="n">df</span><span class="p">[</span><span class="n">columns</span><span class="p">]</span> <span class="o">=</span> <span class="n">scaler</span><span class="o">.</span><span class="n">fit_transform</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="n">columns</span><span class="p">]</span><span class="o">.</span><span class="n">values</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">weights_kwargs</span><span class="p">:</span>
            <span class="n">w0</span> <span class="o">=</span> <span class="n">W</span><span class="o">.</span><span class="n">from_dataframe</span><span class="p">(</span><span class="n">df</span><span class="p">,</span> <span class="o">**</span><span class="n">weights_kwargs</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">w0</span> <span class="o">=</span> <span class="n">W</span><span class="o">.</span><span class="n">from_dataframe</span><span class="p">(</span><span class="n">df</span><span class="p">)</span>
        <span class="n">w1</span> <span class="o">=</span> <span class="n">KNN</span><span class="o">.</span><span class="n">from_dataframe</span><span class="p">(</span><span class="n">df</span><span class="p">,</span> <span class="n">k</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
        <span class="n">ws</span> <span class="o">=</span> <span class="p">[</span><span class="n">w0</span><span class="p">,</span> <span class="n">w1</span><span class="p">]</span>

        <span class="k">if</span> <span class="n">threshold_variable</span> <span class="ow">and</span> <span class="n">threshold_variable</span> <span class="o">!=</span> <span class="s2">&quot;count&quot;</span><span class="p">:</span>
            <span class="n">data</span><span class="p">[</span><span class="n">threshold_variable</span><span class="p">]</span> <span class="o">=</span> <span class="n">gdf</span><span class="p">[</span><span class="n">threshold_variable</span><span class="p">]</span>
            <span class="n">threshold_var</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">threshold_variable</span><span class="o">.</span><span class="n">values</span>
            <span class="n">ws</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">attach_islands</span><span class="p">(</span><span class="n">ws</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">ws</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

        <span class="k">elif</span> <span class="n">threshold_variable</span> <span class="o">==</span> <span class="s2">&quot;count&quot;</span><span class="p">:</span>
            <span class="n">threshold_var</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">ones</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">time</span><span class="p">]))</span>
            <span class="n">ws</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">attach_islands</span><span class="p">(</span><span class="n">ws</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">ws</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

        <span class="k">else</span><span class="p">:</span>
            <span class="n">threshold_var</span> <span class="o">=</span> <span class="kc">None</span>

        <span class="n">model</span> <span class="o">=</span> <span class="n">specification</span><span class="p">[</span><span class="n">method</span><span class="p">](</span>
            <span class="n">df</span><span class="p">[</span><span class="n">columns</span><span class="p">],</span>
            <span class="n">w</span><span class="o">=</span><span class="n">ws</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
            <span class="n">n_clusters</span><span class="o">=</span><span class="n">n_clusters</span><span class="p">,</span>
            <span class="n">threshold_variable</span><span class="o">=</span><span class="n">threshold_var</span><span class="p">,</span>
            <span class="n">threshold</span><span class="o">=</span><span class="n">threshold</span><span class="p">,</span>
            <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="n">labels</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">labels_</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span>
        <span class="n">clusters</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span>
            <span class="p">{</span><span class="n">model_name</span><span class="p">:</span> <span class="n">labels</span><span class="p">,</span> <span class="n">time_var</span><span class="p">:</span> <span class="n">df</span><span class="p">[</span><span class="n">time_var</span><span class="p">],</span> <span class="n">id_var</span><span class="p">:</span> <span class="n">df</span><span class="p">[</span><span class="n">id_var</span><span class="p">]}</span>
        <span class="p">)</span>
        <span class="n">clusters</span> <span class="o">=</span> <span class="n">clusters</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="n">id_var</span><span class="p">])</span>
        <span class="n">clusters</span><span class="o">.</span><span class="n">set_index</span><span class="p">([</span><span class="n">time_var</span><span class="p">,</span> <span class="n">id_var</span><span class="p">],</span> <span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
        <span class="n">gdf</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">clusters</span><span class="p">)</span>
        <span class="n">results</span> <span class="o">=</span> <span class="n">ModelResults</span><span class="p">(</span>
            <span class="n">X</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="n">columns</span><span class="p">]</span><span class="o">.</span><span class="n">values</span><span class="p">,</span>
            <span class="n">columns</span><span class="o">=</span><span class="n">columns</span><span class="p">,</span>
            <span class="n">labels</span><span class="o">=</span><span class="n">model</span><span class="o">.</span><span class="n">labels_</span><span class="p">,</span>
            <span class="n">instance</span><span class="o">=</span><span class="n">model</span><span class="p">,</span>
            <span class="n">W</span><span class="o">=</span><span class="n">ws</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
        <span class="p">)</span>
        <span class="n">models</span><span class="p">[</span><span class="n">time</span><span class="p">]</span> <span class="o">=</span> <span class="n">results</span>

    <span class="n">gdf</span> <span class="o">=</span> <span class="n">gdf</span><span class="o">.</span><span class="n">reset_index</span><span class="p">()</span>

    <span class="k">return</span> <span class="n">gdf</span><span class="p">,</span> <span class="n">models</span><span class="p">,</span> <span class="n">model_name</span></div>
</pre></div>

    </div>
      
  </div>
</div>
<footer class="footer">
  <div class="container">
    <p class="pull-right">
      <a href="#">Back to top</a>
      
        <br/>
        
      
    </p>
    <p>
        &copy; Copyright 2020, geosnap developers.<br/>
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 2.4.4.<br/>
    </p>
  </div>
</footer>
  </body>
</html>